using System;
using System.Collections.Generic;
using OpenTK.Mathematics;
using OpenTK.Windowing.Common;
using OpenTK.Windowing.GraphicsLibraryFramework;

namespace OpenTK.Windowing.Desktop
{
	public class MonitorInfo
	{
		private readonly MonitorHandle _handle;

		private VideoMode[] _supportedVideoModes;

		private unsafe Monitor* HandleAsPtr => _handle.ToUnsafePtr<Monitor>();

		public MonitorHandle Handle => _handle;

		public string Name { get; private set; }

		public Box2i ClientArea { get; private set; }

		public Box2i WorkArea { get; private set; }

		public int HorizontalResolution => ClientArea.Size.X;

		public int VerticalResolution => ClientArea.Size.Y;

		public float HorizontalScale { get; private set; }

		public float VerticalScale { get; private set; }

		public float HorizontalDpi { get; private set; }

		public float VerticalDpi { get; private set; }

		public int PhysicalWidth { get; private set; }

		public int PhysicalHeight { get; private set; }

		public float HorizontalRawDpi { get; private set; }

		public float VerticalRawDpi { get; private set; }

		public IReadOnlyList<VideoMode> SupportedVideoModes => _supportedVideoModes;

		public VideoMode CurrentVideoMode { get; private set; }

		internal unsafe MonitorInfo(MonitorHandle handle)
		{
			GLFWProvider.EnsureInitialized();
			if (handle.Pointer == IntPtr.Zero)
			{
				throw new ArgumentNullException("handle");
			}
			_handle = handle;
			Name = GLFW.GetMonitorName(HandleAsPtr);
			GLFW.GetMonitorPos(HandleAsPtr, out var x, out var y);
			VideoMode* videoMode = GLFW.GetVideoMode(HandleAsPtr);
			ClientArea = new Box2i(x, y, x + videoMode->Width, y + videoMode->Height);
			GLFW.GetMonitorWorkarea(HandleAsPtr, out var x2, out var y2, out var width, out var height);
			WorkArea = new Box2i(x2, y2, x2 + width, y2 + height);
			GLFW.GetMonitorPhysicalSize(HandleAsPtr, out var width2, out var height2);
			PhysicalWidth = width2;
			PhysicalHeight = height2;
			GLFW.GetMonitorContentScale(HandleAsPtr, out var xScale, out var yScale);
			HorizontalScale = xScale;
			VerticalScale = yScale;
			float platformDefaultDpi = Monitors.GetPlatformDefaultDpi();
			HorizontalDpi = platformDefaultDpi * HorizontalScale;
			VerticalDpi = platformDefaultDpi * VerticalScale;
			HorizontalRawDpi = CalculateDpi(HorizontalResolution, PhysicalWidth);
			VerticalRawDpi = CalculateDpi(VerticalResolution, PhysicalHeight);
			_supportedVideoModes = GLFW.GetVideoModes(HandleAsPtr);
			CurrentVideoMode = *GLFW.GetVideoMode(HandleAsPtr);
		}

		private float CalculateDpi(int pixels, int length)
		{
			return (float)pixels / (float)length * 25.4f;
		}
	}
}
